#include <length.h>
#include <MutexLock.h>
#include <structure.h>
#include <OSProc.h>
#include <MC.h>
#include <BasicMatic.h>
extern volatile _mch kmemory;

#define _KMalloc(x)  Kmalloc((_mch*)&kmemory,x)
#define _KFree(x)    Kfree((_mch*)&kmemory,x)

#define _INSERT(_member,_contain,__MAKENODE__,__INSERTNODE__) \
  (_member == NULL						\
   ? (_member = __MAKENODE__(_KMalloc(sizeof(_member)),_contain),1) \
   : (__INSERTNODE__(_member,__MAKENODE__(_KMalloc(sizeof(_member)),_contain)),1)) 
/*					
#define _REMOVE(_member,_contain,__REMOVENODE__)	\
  ({auto fun = [&](decltype(_member) node)->int	\
  {							\
    (node == NULL					\
    ? 0							\
    : ( (((decltype(_contain))(node->mark)) == _contain)	\
	? (__REMOVENODE__(_member,node),_KFree(node),1)	\
	: fun(node->next)				\
	)						\
     );							\
  };fun(_member);})
*/
#define _REMOVE(_member,_contain,__REMOVENODE__)	\
(							\
{							\
decltype(_member) node = _member;			\
while(node != NULL)					\
	node = node->next;				\
(node == NULL						\
? 0							\
: (__REMOVENODE__(_member,node),_KFree(node),1));	\
}							\
)					
namespace HWM
{
  typedef struct HARDWARE_DISCRIPTION hwdd;  
  struct HARDWARE_DISCRIPTION
  {
    _length phyMem;  //Hardware Address: Including different types of address: io address , memory adress ...
    _ptlong state; 
    char name[16];
    _mlock lock;
/*	inline hwdd& operator=(hwdd& source)
	{
		phyMem = source.phyMem;
		state = source.state;
		_Memcpy(name,source.name,sizeof(name));
		lock = source.lock;
	}
*/
  };

  
  typedef slnode hwnode;
  hwdd  _rhardwares = {0,0,{0},{0}};
  hwnode rhardwares = {&_rhardwares,NULL};
  hwnode* hardwares = &rhardwares;
  volatile _mlock hardwareslock ;

  _ptlong HWM_Init()
  {
      MUTEX_Init((_mlock*)&hardwareslock);
  }
  
#define _HWDD(x)  ((hwdd*)(i->mark))
  hwdd* GetHardwareHandle(char* name)
  {
    MUTEX_LOCK(&hardwareslock);
    hwnode* i = hardwares;
    while(i != NULL)
      {
	if(StrCompare(_HWDD(i)->name,name) == 1)
	  {MUTEX_UNLOCK(&hardwareslock);  return _HWDD(i);}
	i = i ->next;
      }
    MUTEX_UNLOCK(&hardwareslock);
    return NULL;
	
  }
  _ptlong ActivateHardware(_pcb* pro,hwdd* handle)
  {
    MUTEX_LOCK(&hardwareslock);
    _ptlong ret;
#define MakeSListNode_(x,y) MakeSListNode((slnode*)x,(void*)y)
    if((ret = MUTEX_TRYLOCK(&(handle->lock))) == 1)
      ret = _INSERT(pro->hwdds,handle,MakeSListNode_,InsertSListNode);

    MUTEX_UNLOCK(&hardwareslock);
    return ret;

  }
  _ptlong InactivateHardware(_pcb* pro,hwdd* handle)
  {
    MUTEX_LOCK(&hardwareslock);
    _ptlong ret;
    if((ret = MUTEX_UNLOCK(&(handle->lock))) == 1)
      ret = _REMOVE(pro->hwdds,handle,RemoveSListNode);
    
    MUTEX_UNLOCK(&hardwareslock);
    return ret;
    
  }
  hwdd* AddHardware(char* name,_length phyMem,_ptlong state)
  {
    MUTEX_LOCK(&hardwareslock);
    hwdd* handle =
      ({
	hwdd* newhandle =  (hwdd*)_KMalloc(sizeof(hwdd));
	//*newhandle = {phyMem,state,{0},(_mlock){NULL,NULL,0}};
	(*newhandle).phyMem = phyMem;(*newhandle).state = state;MUTEX_Init(&(*newhandle).lock);
	MUTEX_Init(&(newhandle->lock));
	_Memcpy(name,&(newhandle->name),strlength(name)+1);
	newhandle;
      });
    _INSERT(hardwares,handle,MakeSListNode_,InsertSListNode);
#undef MakeSListNode_(x,y)
    MUTEX_UNLOCK(&hardwareslock);
    return handle;
  }
  _ptlong DelHardware(hwdd* handle)
  {
    MUTEX_LOCK(&hardwareslock);
    _ptlong ret =_REMOVE(hardwares,handle,RemoveSListNode);
    MUTEX_UNLOCK(&hardwareslock);
    return ret;
  }

}

using namespace HWM;
